﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Beeldbankmvc.Code;
using Beeldbankmvc.ViewModels;

namespace Beeldbankmvc.Models
{
    public class MediaObjectRepository
    {
        BeeldbankLinqDataContext db = new BeeldbankLinqDataContext();
        
        public BeeldbankLinqDataContext GetDataContext()
        {
            return db;
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindAllSortedByType(int typeId)
        {
            return from p in FindAllSorted()
                   where p.TypeId == typeId
                   orderby p.Titel
                   select p;
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindAllSorted()
        {
            return from p in FindAll()
                   orderby p.Titel
                   select p;
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindAllSortedByCreation()
        {
            return (from p in FindAll()
                    orderby p.createdat
                    select p).Take(20);
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindAll()
        {
            return db.BEELDBANK_MEDIAOBJECTs;
        }

        public BEELDBANK_MEDIAOBJECT FindOne(int id)
        {
            return db.BEELDBANK_MEDIAOBJECTs.SingleOrDefault(m => m.Id == id);
        }

        public BEELDBANK_MEDIAOBJECT FindOneByFileNumber(int fileNumber)
        {
            return db.BEELDBANK_MEDIAOBJECTs.SingleOrDefault(m => m.FileNummer == fileNumber);
        }

        public BEELDBANK_MEDIAOBJECT FindOneByTitle(string title)
        {
            return db.BEELDBANK_MEDIAOBJECTs.SingleOrDefault(m => m.Titel == title);
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindMostRecentCreated(int count)
        {
            return FindAll().Where(m => m.StatusId == Constants.ITEM_STATUS_EXTERN).OrderByDescending(m => m.Id).Take(count);
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindMostRecentModified(int count)
        {
            //return (from p in FindAll()
            //       where p.modifiedat != p.createdat
            //       &&
            //       p.StatusId == 11911
            //       orderby p.modifiedat descending
            //       select p).Take(count);

            return FindAll().Where(m => m.StatusId == Constants.ITEM_STATUS_EXTERN && m.modifiedat != m.createdat).OrderByDescending(m => m.modifiedat).Take(count);
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindAddedToday()
        {
            return from p in FindAll()
                   where p.createdat.DayOfYear == DateTime.Today.DayOfYear
                   &&
                   p.createdat.Year == DateTime.Today.Year
                   &&
                   p.StatusId == Constants.ITEM_STATUS_EXTERN
                   select p;
        }

        public IQueryable<BEELDBANK_MEDIAOBJECT> FindAllByFileNumber(int filenummer)
        {
            return from p in FindAll()
                   where p.FileNummer == filenummer
                   orderby p.Id
                   select p;
        }

        public int FindCountByTitle(string title)
        {
            return db.BEELDBANK_MEDIAOBJECTs.Count(m => m.Titel == title);
        }

        public BEELDBANK_MEDIAOBJECT FindNextByTitle(string title, int id)
        {
            return db.BEELDBANK_MEDIAOBJECTs.SingleOrDefault(m => m.Titel == title && m.Id != id);
        }

        public void UpdateDescription(int id, string description)
        {
            BEELDBANK_MEDIAOBJECT mediaObject = FindOne(id);
            mediaObject.Omschrijving = description;

            Save();
        }

        public string CalculateKeywords(int id)
        {
            BEELDBANK_MEDIAOBJECT mediaObject = FindOne(id);
            
            String description = mediaObject.Omschrijving + " " + mediaObject.Titel;

            description = AppHelper.filterOutHTML(description, " ");
            description = AppHelper.filterOutSpecialCharacters(description);

            if (!String.IsNullOrEmpty(description))
            {
                description = description.Replace("\r", " ");
                description = description.Replace("\n", " ");
                String[] descritionWords = description.Split(' ');

                var keywords =
                    from c in GetDataContext().BEELDBANK_WORDs
                    select c.Word;

                var foundKeyWords = descritionWords.Intersect(keywords, StringComparer.CurrentCultureIgnoreCase);

                // keywords are always regenerated from the description text
                mediaObject.Trefwoorden = "";
                foreach (var x in foundKeyWords)
                {
                    mediaObject.Trefwoorden += x + " | ";
                }

                // Loop trough all collections and create a custom collection object
                var collections = from a in GetDataContext().BEELDBANK_COLLECTIONs select new { keyword = a.Keywords, name = a.Name, id = a.Id };

                CollectionRepository CollectionRepository = new CollectionRepository();

                // loop trough the collection object
                foreach (var coll in collections)
                {
                    // get a key words array from the keywords column 
                    string[] keywordStringWords = coll.keyword.Split('|');

                    // check is the foundKeywords of this item are in this collection
                    var foundKeyWordsInThisCollection = keywordStringWords.Intersect(foundKeyWords, StringComparer.CurrentCultureIgnoreCase);

                    // add this collection to the mediaObject

                    foreach (var x in foundKeyWordsInThisCollection)
                    {
                        // test adding a related collection
                        BEELDBANK_MEDIAOBJECT_COLLECTION relatedCollection = new BEELDBANK_MEDIAOBJECT_COLLECTION();
                        relatedCollection.CollectionId = coll.id;


                        if (!mediaObject.BEELDBANK_MEDIAOBJECT_COLLECTIONs.Contains(relatedCollection, new MyCollectionObjectComparer()))
                        {
                            mediaObject.BEELDBANK_MEDIAOBJECT_COLLECTIONs.Add(relatedCollection);
                        }
                    }
                }
            }
            return mediaObject.Trefwoorden;
        }

        public void Add(BEELDBANK_MEDIAOBJECT mediaObject)
        {
            db.BEELDBANK_MEDIAOBJECTs.InsertOnSubmit(mediaObject);
        }

        public void Delete(BEELDBANK_MEDIAOBJECT mediaObject)
        {
            db.BEELDBANK_MEDIAOBJECTs.DeleteOnSubmit(mediaObject);
        }

        public IEnumerable<FilmStripItemModel> getRandomItems(int numberOfRequestedItems, Mediatypes.MediaTypes randomType)
        {
            var searchCounts = from p in db.BEELDBANK_CUSTOM_MEDIAOBJECT_BANNERROTATOR((int)randomType)
                               select new FilmStripItemModel { Id = p.MediaObjectId, ImageDescription = p.Omschrijving };

            return searchCounts.Take(numberOfRequestedItems);
        }

        public IEnumerable<FilmStripItemModel> getUnknownItems(int numberOfRequestedItems, Mediatypes.MediaTypes randomType)
        {
            var searchCounts = from p in db.BEELDBANK_CUSTOM_MEDIAOBJECT_BANNERROTATOR((int)randomType)
                               select new FilmStripItemModel { Id = p.MediaObjectId, ImageDescription = p.Omschrijving };

            return searchCounts.Take(numberOfRequestedItems);
        }

        public void Save()
        {
            db.SubmitChanges();
        }

        private void InsertViewCounter(int MediaObjectId, string publicationName)
        {
            IFormatProvider culture = new CultureInfo("nl-NL", true);

            BEELDBANK_VIEW_COUNTER counter = new BEELDBANK_VIEW_COUNTER();
            counter.CreationDate = DateTime.Now;
            counter.LastUpdate = DateTime.Now;
            counter.MediaObjectId = MediaObjectId;
            counter.ViewCount = 1;
            counter.Publicatie = publicationName;

            db.BEELDBANK_VIEW_COUNTERs.InsertOnSubmit(counter);
            db.SubmitChanges();
        }

        public void IncreaseViewCounter(int MediaObjectId, string publicationName)
        {
            BEELDBANK_VIEW_COUNTER counter = db.BEELDBANK_VIEW_COUNTERs.SingleOrDefault(m => m.MediaObjectId == MediaObjectId && m.Publicatie.Equals(publicationName));

            if (counter == null)
            {
                this.InsertViewCounter(MediaObjectId, publicationName);
            }
            else
            {
                counter.LastUpdate = DateTime.Now;
                counter.ViewCount = counter.ViewCount + 1;
                counter.Publicatie = publicationName;
                db.SubmitChanges();
            }
        }

        public int PostBack(int bbfileid, string tridionId)
        {
            BEELDBANK_MEDIAOBJECT mediaObject = db.BEELDBANK_MEDIAOBJECTs.SingleOrDefault(m => m.FileNummer == bbfileid);
            mediaObject.TridionId = tridionId;
            db.SubmitChanges();

            return mediaObject.Id;
        }

        public string commaSeparatedCollections(int MediaObjectId)
        {
            var q =
            from c in db.BEELDBANK_MEDIAOBJECT_COLLECTIONs
            join p in db.BEELDBANK_COLLECTIONs on c.CollectionId equals p.Id
            where c.MediaObjectId == MediaObjectId
            select new { Category = c, p.Name };

            string retVar = "";
            foreach (var v in q)
            {
                retVar += v.Name + ",";
            }

            return retVar;
        }

        public void CleanupUnwantedShowInBanner(int pageSize, int pageIndex)
        {
            CollectionRepository repository = new CollectionRepository();

            foreach (BEELDBANK_MEDIAOBJECT item in (from m in FindAll()
                                                   where m.UseInBanner == true
                                                   &&
                                                   m.TypeId == Constants.ITEM_TYPE_DIGITAL
                                                   select m).Skip(pageIndex * pageSize).Take(pageSize))
            {
                // If item is NOT part of the 5 Star collection, remove the status UseInBanner
                if (repository.FindCollectionByName(item.Id, "5 Sterren") <= 0)
                    RemoveFromDisplayInBanner(item.Id);
            }
        }

        public List<FiveStarMedia> getAllFotosWithFiveStars(int pageSize, int pageIndex)
        {
            var itemList =
                (from m in FindAll()
                where m.UseInBanner == true
                &&
                m.TypeId == Constants.ITEM_TYPE_DIGITAL
                select new FiveStarMedia
                {
                    BeeldbankMediaObject = m,
                    HasFiveStarCollection = false
                }).Skip(pageIndex * pageSize).Take(pageSize);

            CollectionRepository repository = new CollectionRepository();
            List<FiveStarMedia> fiveStarMediaObjects = new List<FiveStarMedia>();

            foreach (FiveStarMedia item in itemList)
            {
                if (repository.FindCollectionByName(item.BeeldbankMediaObject.Id, "5 Sterren") > 0)
                    item.HasFiveStarCollection = true;
                fiveStarMediaObjects.Add(item);
            }

            return fiveStarMediaObjects;
        }

        public int getAllFotosWithFiveStarsCount()
        {
            return (
                from m in FindAll()
                where m.UseInBanner == true
                &&
                m.TypeId == Constants.ITEM_TYPE_DIGITAL
                select new FiveStarMedia
                {
                    BeeldbankMediaObject = m,
                    HasFiveStarCollection = false
                }
                ).Count();
        }

        public void AddTo5Stars(int MediaObjectId)
        {
            CollectionRepository repository = new CollectionRepository();
            CollectionModel model = repository.FindOneByName("5 Sterren");

            if (model != null)
            {
                BEELDBANK_MEDIAOBJECT_COLLECTION newCollection = new BEELDBANK_MEDIAOBJECT_COLLECTION();
                newCollection.CollectionId = model.Id;
                newCollection.MediaObjectId = MediaObjectId;

                db.BEELDBANK_MEDIAOBJECT_COLLECTIONs.InsertOnSubmit(newCollection);
            }
        }

        public void RemoveFrom5Stars(int MediaObjectId)
        {
            CollectionRepository repository = new CollectionRepository();
            CollectionModel model = repository.FindOneByName("5 Sterren");

            if (model != null)
            {
                BEELDBANK_MEDIAOBJECT_COLLECTION existingCollection = new BEELDBANK_MEDIAOBJECT_COLLECTION();
                existingCollection.CollectionId = model.Id;
                existingCollection.MediaObjectId = MediaObjectId;

                db.BEELDBANK_MEDIAOBJECT_COLLECTIONs.Attach(existingCollection);
                db.BEELDBANK_MEDIAOBJECT_COLLECTIONs.DeleteOnSubmit(existingCollection);
                Save();
            }
        }

        public void RemoveFromDisplayInBanner(int MediaObjectId)
        {
            BEELDBANK_MEDIAOBJECT mediaObject = db.BEELDBANK_MEDIAOBJECTs.SingleOrDefault(m => m.Id == MediaObjectId);
            mediaObject.UseInBanner = false;
        }

                public class MyCollectionObjectComparer : IEqualityComparer<BEELDBANK_MEDIAOBJECT_COLLECTION>
        {
            public bool Equals(BEELDBANK_MEDIAOBJECT_COLLECTION a, BEELDBANK_MEDIAOBJECT_COLLECTION b)
            {
                return a.CollectionId == b.CollectionId;
            }

            public int GetHashCode(BEELDBANK_MEDIAOBJECT_COLLECTION collectionObject)
            {
                return collectionObject.CollectionId.GetHashCode();
            }
        }

    }
}